from copy import copy
from dataclasses import dataclass
from logging import INFO
from typing import List, Optional

from vnpy.event import Event
from vnpy.trader.constant import Offset, Direction, Exchange, OrderType
from vnpy.trader.event import EVENT_LOG
from vnpy.trader.object import LogData, PositionData, AccountData, OrderData, TradeData, OrderRequest, ContractData
from vnpy.trader.utility import round_to
from vnpy_scripttrader import APP_NAME, ScriptEngine


@dataclass
class AccountModelData:
    """
    Account
    """

    id: int
    username: str
    account: str
    password: str
    broker: int
    trade_server: str
    quotation_server: str
    product_name: str
    authorization_code: str
    init_balance: float


@dataclass
class RiskManagerModelData:
    id: int
    username: str
    account: str
    max_loss: float
    sleep: int


@dataclass
class ExtendedLogData(LogData):
    """
    Extended log data with additional accountid field.
    """
    accountid: str = ""


@dataclass
class ExtendedPositionData(PositionData):
    """
    Position data is used for tracking each individual position holding.
    """

    accountid: str = ""

    def __post_init__(self) -> None:
        """"""
        self.vt_symbol: str = f"{self.symbol}.{self.exchange.value}"
        self.vt_positionid: str = f"{self.accountid}.{self.gateway_name}.{self.vt_symbol}.{self.direction.value}"


@dataclass
class ExtendedOrderData(OrderData):
    """
    """

    accountid: str = ""

    def __post_init__(self) -> None:
        """"""
        self.vt_symbol: str = f"{self.symbol}.{self.exchange.value}"
        self.vt_orderid: str = f"{self.accountid}.{self.gateway_name}.{self.orderid}"


@dataclass
class ExtendedAccountData(AccountData):
    init_balance: float = ""
    thre_balance: float = ""


@dataclass
class ExtendedTradeData(TradeData):
    """
    """
    accountid: str = ""


class ExtendedScriptEngine(ScriptEngine):
    def write_log(self, msg: str) -> None:
        """"""
        log: LogData = LogData(msg=msg, gateway_name=APP_NAME)

        event: Event = Event(EVENT_LOG, log)
        self.event_engine.put(event)

    def send_order(
            self,
            vt_symbol: str,
            price: float,
            volume: float,
            direction: Direction,
            offset: Offset,
            order_type: OrderType,
    ):
        """"""
        contract: Optional[ContractData] = self.get_contract(vt_symbol)
        if not contract:
            self.write_log(f"委托失败，找不到合约：{vt_symbol}")
            return ""
        # Round order price and volume to nearest incremental value
        price = round_to(price, contract.pricetick)
        volume = round_to(volume, contract.min_volume)

        original_req: OrderRequest = OrderRequest(
            symbol=contract.symbol,
            exchange=contract.exchange,
            direction=direction,
            type=order_type,
            volume=volume,
            price=price,
            offset=offset,
            reference=APP_NAME
        )
        # Convert with offset converter
        req_list = self.main_engine.convert_order_request(original_req, contract.gateway_name, lock=False)
        # Send Orders
        vt_orderids = []

        for req in req_list:
            vt_orderid = self.main_engine.send_order(req, contract.gateway_name)

            # Check if sending order successful
            if not vt_orderid:
                continue

            vt_orderids.append(vt_orderid)

            self.main_engine.update_order_request(req, vt_orderid, contract.gateway_name)

        return vt_orderids
